package com.hjy.attendance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hjy.attendance.ai.AiFaceTemplate;
import com.hjy.attendance.context.IMContextHolder;
import com.hjy.attendance.dao.FaceInformationDao;
import com.hjy.attendance.entity.*;
import com.hjy.attendance.enums.ResultEnum;
import com.hjy.attendance.exception.ApiException;
import com.hjy.attendance.role.RoleType;
import com.hjy.attendance.service.AttendanceParentService;
import com.hjy.attendance.service.AttendanceSonService;
import com.hjy.attendance.service.FaceInformationService;
import com.hjy.attendance.service.UserService;
import com.hjy.attendance.util.IPUtil;
import com.hjy.attendance.util.JwtUtil;
import com.hjy.attendance.util.ValidUtil;
import com.hjy.attendance.util.WebUtils;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>标题:  Service 实现类</p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2020</p>
 *
 * @version: 1.0
 * @author: huangjunyu
 * @date 2020-04-18
 */
@Service
@Slf4j
public class FaceInformationServiceImpl extends BaseServiceImpl<FaceInformationDao, FaceInformation> implements FaceInformationService {

    @Autowired
    AttendanceParentService attendanceParentService;

    @Autowired
    AttendanceSonService attendanceSonService;

    @Autowired(required = false)
    AiFaceTemplate aiFaceTemplate;

    @Autowired
    UserService userService;

    @Override
    public JSONObject addUser(MultipartFile file, User user) throws Exception {
        String result=aiFaceTemplate.addUser(file,user,"1".equals(user.getPermissionCode())?RoleType.STUDENT:("2".equals(user.getPermissionCode())?RoleType.TEACHER:RoleType.ADMIN));
        return JSON.parseObject(result);
    }

    @Override
    public JSONObject checkFace(MultipartFile file, String compareId) throws Exception {
        return JSON.parseObject(aiFaceTemplate.checkFace(file,compareId));
    }

    @Override
    public JSONObject serachFace(MultipartFile file) throws Exception {
        return JSON.parseObject(this.aiFaceTemplate.searchFace(file));
    }

    @Override
    public JSONObject checkFace(String base64Img, String attendanceId) throws ApiException {
        String userId= JwtUtil.decode(IMContextHolder.get("token"));
        FaceInformation faceInformation=getOne(new QueryWrapper<>(FaceInformation.builder().userId(userId).build()));
        Date date=new Date();
        AttendanceParent parent=this.attendanceParentService.getById(attendanceId);
        if (faceInformation==null){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"当前人脸库中并无你的信息，请联系管理员采集人脸");
        }
        if (parent==null){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"该考勤任务已经不存在");
        }
        if (parent.getTotalSuccessFlag()==1){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"已经超过考勤允许时间");
        }
        QueryWrapper<AttendanceSon> queryWrapper=new QueryWrapper<AttendanceSon>(AttendanceSon.builder().userId(userId).attentanceParentId(attendanceId).build());
        AttendanceSon attendanceSon=this.attendanceSonService.getOne(queryWrapper);
        if (attendanceSon==null){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"你已不在该考勤任务之内,请联系管理员是否恢复");
        }
        if (attendanceSon.getSuccessFlag()==1){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"你已经考勤过,不可重复操作");
        }
        JSONObject res=JSON.parseObject(aiFaceTemplate.compareWithTwoImh(new String(faceInformation.getFaceContent()),base64Img));
        if (!ValidUtil.isEmptyOrNull(res.getInteger("error_code")) && res.getInteger("error_code").equals(223114)){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"图像模糊,人脸识别失败");
        }
        if (!ValidUtil.isEmptyOrNull(res.getInteger("error_code")) && res.getInteger("error_code").equals(222207)){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"找不到匹配的人脸");
        }
        if (res.getInteger("error_code")==0 &&  !ValidUtil.isEmptyOrNull(res.getJSONObject("result"))){
            BigDecimal bigDecimal=res.getJSONObject("result").getBigDecimal("score");
            int standard=faceInformation.getStandardScore();
            if (bigDecimal.intValue()>=standard){
                attendanceSon.setSuccessFlag(1);
                attendanceSon.setAttentanceFlag(date.getTime()>parent.getAttendanceExpectStartTime().getTime()?0:1);
                attendanceSon.setAttentanceRecordStartTime(date);
                attendanceSon.setIpv4Address(IPUtil.getIpAddr((HttpServletRequest) WebUtils.getCurrentRequest()));
                this.attendanceSonService.updateById(attendanceSon);
            }else{
                throw  new ApiException(ResultEnum.CUSTOMFAILURE,"匹配失败,建议调整比分阈值");
            }

        }
        return res;
    }

    @Override
    public List<Map<String, Object>> getALlFaces() throws Exception {
        List<Map<String,Object>> result=this.baseDao.getALlFaces();
        result=result.stream().peek(data->{
            if (!ValidUtil.isEmptyOrNull(data.get("guid"))){
                data.put("faceContent",new String((byte[])data.get("faceContent")));
            }

        }).collect(Collectors.toList());
        return result;
    }

    @Override
    public void addFace(Map<String, Object> param) throws Exception {
        byte[] faceContent=param.get("faceContent").toString().getBytes("utf-8");
        String userId=param.get("userId").toString();
        if (userService.getById(userId)==null){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"不存在此用户");
        }
        int standardScore=Integer.valueOf(param.get("standardScore").toString());
        FaceInformation faceInformation=getOne(new QueryWrapper<>(FaceInformation.builder().userId(userId).build()));
        if (faceInformation==null){
            FaceInformation information=FaceInformation.builder()
                    .createTime(new Date())
                    .updateTime(new Date())
                    .guid(UUID.randomUUID().toString())
                    .faceContent(faceContent)
                    .standardScore(standardScore)
                    .userId(userId)
                    .validFlag(1)
                    .build();
            insert(information);
        }else{
            deleteById(faceInformation.getGuid());
            faceInformation.setGuid(UUID.randomUUID().toString());
            faceInformation.setFaceContent(faceContent);
            faceInformation.setStandardScore(standardScore);
            faceInformation.setUpdateTime(new Date());
            insert(faceInformation);
        }

    }

    @Override
    public String judgeBeforePublishLeave(String image,String StudentNo) throws Exception {
        FaceInformation faceInformation= Optional.<FaceInformation>ofNullable(getOne(new QueryWrapper<>(FaceInformation.builder().userId(StudentNo).build())))
                .orElseThrow(()->new ApiException(ResultEnum.CUSTOMFAILURE,"你的人脸信息不完整,请联系管理员进行录入"));
        String compareImg=new String(faceInformation.getFaceContent());
        JSONObject res=JSON.parseObject(aiFaceTemplate.compareWithTwoImh(image,compareImg));
        if (!ValidUtil.isEmptyOrNull(res.getInteger("error_code")) && res.getInteger("error_code").equals(223114)){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"图像模糊,人脸识别失败");
        }
        if (!ValidUtil.isEmptyOrNull(res.getInteger("error_code")) && res.getInteger("error_code").equals(222207)){
            throw new ApiException(ResultEnum.CUSTOMFAILURE,"找不到匹配的人脸");
        }
        if (res.getInteger("error_code")==0 &&  !ValidUtil.isEmptyOrNull(res.getJSONObject("result"))){
            BigDecimal bigDecimal=res.getJSONObject("result").getBigDecimal("score");
            int standard=faceInformation.getStandardScore();
            if (bigDecimal.intValue()<standard){
                throw   new ApiException(ResultEnum.CUSTOMFAILURE,"匹配失败,建议调整比分阈值");
            }
        }
        return "success";
    }


    public JSONObject checkFaceSource(String base64Img, String compareId) throws ApiException {
        return JSON.parseObject(this.aiFaceTemplate.checkFace(base64Img,compareId));
    }


}
